#ifndef TEMPLE_MOD_TCP_SERVER_H_
#define TEMPLE_MOD_TCP_SERVER_H_

#include "util/stdc.h"
#include "util/pool.h"
#include <thread>
#include <functional>
namespace mod {

class Listener
{
public:
    Listener();
    ~Listener();

    struct Config
    {
        int local_af;
        string local_addr;
        int local_port;

        std::function<void(u64 cid, const char *addr, int port)> accepted;
        std::function<void(u64 cid, const char *addr, int port, strref &&str)> received;
        std::function<void(u64 cid)> closed;
    };

    int start(const Config &conf);
    void stop();

	void send(u64 cid, const string &str);
	void send(u64 cid, string &&str);
    void close(u64 cid);

private:
    bool alive;
    std::thread *thread;
    util::Logger logger;
    Config config;
    void main_entry();
    static void entry(void *arg);

    int listen_fd;
    int event_fd;
    int epoll_fd;

    struct Dock
    {
        u64 cid;
        int sock;
        time_t tm;

        char addr[64];
        int port;

        char *buffer;
        int offset;
        int length;
    };

    util::ObjectPool<Dock> dock_pool;
    std::map<u64, Dock *>dock_map;

    Dock *alloc_dock(int fd);
    void free_dock(Dock *dock);

    Dock listen_dock;
    Dock event_dock;

    void epoll_add(Dock *dock);
    void epoll_del(Dock *dock);
    void epoll_ro(Dock *dock);
    void epoll_rw(Dock *dock);

    struct Event
    {
        uint64 cid;
        string str;
    };

    util::Queue<Event> cache_queue;

    void period_handler();
    void event_handler(Dock *dock, struct epoll_event &ee);
};

}
#endif //TEMPLE_MOD_TCP_SERVER_H_
